﻿using System;
using Net.System;
using Net.Helper;

namespace Net.Share
{
    /// <summary>
    /// 适配器类型
    /// </summary>
    public enum AdapterType
    {
        /// <summary>
        /// 序列化适配器类型
        /// </summary>
        Serialize,
        /// <summary>
        /// 远程过程调用类型
        /// </summary>
        Rpc,
        /// <summary>
        /// 封包类型
        /// </summary>
        Package,
        /// <summary>
        /// 网络事件类型
        /// </summary>
        Event,
    }

    /// <summary>
    /// 适配器模式
    /// </summary>
    public enum AdapterMode
    {
        /// <summary>
        /// 没有正确指定项目
        /// </summary>
        None,
        /// <summary>
        /// 是服务器的适配器
        /// </summary>
        Server,
        /// <summary>
        /// 是客户端的适配器
        /// </summary>
        Client,
        /// <summary>
        /// 是客户端的适配器, 直接调用, 这个模式是客户端处于自定义模式时使用
        /// </summary>
        ClientDirect,
    }

    /// <summary>
    /// 基础适配器接口
    /// </summary>
    public interface IAdapter
    {
    }

    /// <summary>
    /// 序列化适配器
    /// </summary>
    public interface ISerializeAdapter : IAdapter
    {
        /// <summary>
        /// 当序列化远程过程调用模型
        /// </summary>
        /// <param name="segment"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        bool OnSerializeRpc(ISegment segment, IRpcModel model);

        /// <summary>
        /// 当反序列化远程过程调用模型
        /// </summary>
        /// <param name="segment"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        bool OnDeserializeRpc(ISegment segment, IRpcModel model);

        /// <summary>
        /// 当序列化帧同步操作列表
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        byte[] OnSerializeOpt(in OperationList list);

        /// <summary>
        /// 当反序列化帧同步操作列表
        /// </summary>
        /// <param name="segment"></param>
        /// <returns></returns>
        OperationList OnDeserializeOpt(ISegment segment);
    }

    /// <summary>
    /// 客户端RPC适配器
    /// </summary>
    public interface IRpcAdapter : IAdapter
    {
        /// <summary>
        /// 适配器模式
        /// </summary>
        AdapterMode Mode { get; set; }
        /// <summary>
        /// 输出调用网络函数
        /// </summary>
        bool LogRpc { get; set; }
        /// <summary>
        /// 收集的Rpc方法字典
        /// </summary>
        MyDictionary<uint, RpcMethodList> RpcMethods { get; set; }
        /// <summary>
        /// 字段同步信息
        /// </summary>
        MyDictionary<ushort, SyncVarInfo> SyncVarDic { get; set; }
        /// <summary>
        /// 跨线程调用任务队列
        /// </summary>
        JobQueueHelper WorkerQueue { get; set; }
        /// <summary>
        /// 添加Rpc
        /// </summary>
        /// <param name="target">注册的对象实例</param>
        /// <param name="mode">一个Rpc方法是否可以多次添加到Rpcs里面？</param>
        /// <param name="onSyncVarCollect">字段同步收集回调</param>
        void AddRpc(object target, AddRpcMode mode = AddRpcMode.None, Action<SyncVarInfo> onSyncVarCollect = null);
        /// <summary>
        /// 移除target的所有rpc
        /// </summary>
        /// <param name="target"></param>
        void RemoveRpc(object target);
        /// <summary>
        /// Rpc压入队列
        /// </summary>
        /// <param name="state"></param>
        /// <param name="model"></param>
        void Enqueue(object state, IRpcModel model);
        /// <summary>
        /// 执行远程过程调用
        /// </summary>
        void Execute();
        /// <summary>
        /// 获取或添加Rpc方法体
        /// </summary>
        /// <param name="protocol"></param>
        /// <returns></returns>
        RpcMethodList GetOrAddRpcMethodList(uint protocol);
        /// <summary>
        /// 复制Rpc适配器实例
        /// </summary>
        /// <returns></returns>
        IRpcAdapter Copy();
    }

    /// <summary>
    /// 网络事件适配器
    /// </summary>
    public interface IEventAdapter : INetworkHandle, IAdapter
    {
    }

    /// <summary>
    /// 数据包适配器
    /// </summary>
    public interface IPackageAdapter : IAdapter
    {
        /// <summary>
        /// 头部预留长度
        /// </summary>
        int HeadLength { get; set; }

        /// <summary>
        /// 读取头部数据长度
        /// </summary>
        /// <param name="stream"></param>
        /// <returns>如果返回的是小于0则为状态码, -1是CRC校验失败, -2是数据大小错误</returns>
        int ReadHead(ISegment stream);

        /// <summary>
        /// 封包
        /// </summary>
        /// <param name="stream"></param>
        void Pack(ISegment stream);

        /// <summary>
        /// 解包
        /// </summary>
        /// <param name="stream"></param>
        /// <returns>返回状态码 -1:CRC校验失败 其他自己判断</returns>
        int Unpack(ISegment stream);
    }
}
